import numpy as np

from init import *
from sklearn.decomposition import PCA
from skfuzzy.cluster import cmeans
import copy
from collections import Counter

from init import *
from method import *
import pandas as pd

plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']
plt.rcParams['axes.unicode_minus'] = False


def  get_feature(img_data, flag, ksize, v, h, complexs, key, bestkey,datakey):
    '''
    对图像的特征进行提取
    :param img_data: 图像信息
    :param flag: 奇数点还是偶数点
    :return:
    '''
    row, col = img_data.shape
    size = int((row * col) / 2)
    F = np.zeros((ksize, size))
    # 预测点
    predict = np.zeros((row, row))
    # 误差值
    erromap = np.ones((row, row)) * 999
    typemap = np.zeros((row, col))
    test1 = np.zeros((row, col))
    test2 = np.zeros((row, col))
    index = 0

    c = bin(bestkey)
    # d =
    c = ''.join(c[2:])
    d = []
    d.__iadd__(c)
    d = np.array(d, dtype=int)
    chooselist = np.zeros(8)
    chooselist[8 - len(d):] = d
    # datakey = np.array([4, 5, 9, 1, 3, 16, 0, 2, 8, 10])
    # datakey = np.array([ 4,  5 , 9 , 1 , 3 ,16 , 0 ,2])
    datakey = datakey * chooselist
    # print(datakey)
    # print(chooselist)
    datakey = datakey[datakey != 0]
    for i in range(2, row - 2):
        for j in range(2, col - 2):

            if complexs[i][j] < key:
                # 像素上下左右四个像素
                # 像素上下左右四个像素
                v1 = int(img_data[i - 1][j])
                v2 = int(img_data[i][j - 1])
                v3 = int(img_data[i + 1][j])
                v4 = int(img_data[i][j + 1])
                # 选中点
                x = int(img_data[i][j])
                # 其他九个点
                v5 = int(img_data[i - 2][j - 1])
                v6 = int(img_data[i - 1][j - 2])
                v7 = int(img_data[i + 1][j - 2])
                v8 = int(img_data[i + 2][j - 1])
                v9 = int(img_data[i + 2][j + 1])
                v10 = int(img_data[i + 1][j + 2])
                v11 = int(img_data[i - 1][j + 2])
                v12 = int(img_data[i - 2][j + 1])
                # 左梯度和右梯度
                lg = np.array([[v5 - v1, v2 - v1], [v1 - v4, v3 - v4], [v2 - v3, v8 - v3], [v6 - v2, v7 - v2]])
                rg = np.array([[v12 - v1, v4 - v1], [v11 - v4, v10 - v4], [v4 - v3, v9 - v3], [v1 - v2, v3 - v2]])

                # 从特征11开始为wang以外的特征
                t0 = np.array(
                    [int(img_data[i][j - 1]), int(img_data[i][j + 1]),
                     np.round(int(img_data[i][j - 1] + img_data[i][j + 1]) / 2)])
                t45 = np.array(
                    [img_data[i][j + 1], img_data[i + 1][j],
                     np.round(int(img_data[i][j + 1] + img_data[i + 1][j]) / 2)])
                t90 = np.array(
                    [img_data[i + 1][j], img_data[i - 1][j],
                     np.round(int(img_data[i + 1][j] + img_data[i - 1][j]) / 2)])
                t135 = np.array(
                    [img_data[i][j - 1], img_data[i + 1][j],
                     np.round(int(img_data[i][j - 1] + img_data[i + 1][j]) / 2)])
                u = np.mean([int(img_data[i][j - 1] + img_data[i][j + 1]) / 2,
                             int(img_data[i][j + 1] + img_data[i + 1][j]) / 2,
                             int(img_data[i + 1][j] + img_data[i - 1][j]) / 2,
                             int(img_data[i][j - 1] + img_data[i + 1][j]) / 2])
                t1 = np.sum(np.square(t0 - u))
                t2 = np.sum(np.square(t45 - u))
                t3 = np.sum(np.square(t90 - u))
                t4 = np.sum(np.square(t135 - u))

                # 特征14
                if j - 3 > 0 and j + 3 < 511:
                    x7arr = np.array([img_data[i][j - 3], img_data[i][j - 1], img_data[i][j + 1], img_data[i][j + 3]])
                else:
                    x7arr = np.array([img_data[i][j - 1], img_data[i][j + 1]])
                u1 = np.mean(x7arr)
                # 特征15
                if i - 3 > 0 and i + 3 < 511:
                    x8arr = np.array([img_data[i - 3][j], img_data[i - 1][j], img_data[i + 1][j], img_data[i + 3][j]])
                else:
                    x8arr = np.array([img_data[i - 1][j], img_data[i + 1][j]])
                u2 = np.mean(x8arr)
                # 特征16
                Vu = np.array([img_data[i - 1][j - 2], img_data[i - 2][j - 1], img_data[i][j - 1],
                               img_data[i - 1][j], img_data[i - 2][j + 1], img_data[i][j + 1],
                               img_data[i - 1][j + 2]]
                              )
                Vb = np.array([img_data[i + 1][j - 2], img_data[i][j - 1], img_data[i + 2][j - 1],
                               img_data[i + 1][j], img_data[i][j + 1], img_data[i + 2][j + 1],
                               img_data[i + 1][j + 2]]
                              )
                Hl = np.array([img_data[i - 2][j - 1], img_data[i - 1][j - 2], img_data[i - 1][j],
                               img_data[i][j - 1], img_data[i + 1][j - 2], img_data[i + 1][j],
                               img_data[i + 2][j - 1]]
                              )
                Hr = np.array([img_data[i - 2][j + 1], img_data[i - 1][j], img_data[i - 1][j + 2],
                               img_data[i][j + 1], img_data[i + 1][j], img_data[i + 1][j + 2],
                               img_data[i + 2][j + 1]]
                              )
                # 特征17
                V10 = np.array([img_data[i - 2][j - 1], img_data[i - 2][j + 1], img_data[i - 1][j - 2],
                                img_data[i - 1][j], img_data[i - 1][j + 2], img_data[i][j - 1],
                                img_data[i][j + 1], img_data[i + 1][j - 2], img_data[i + 1][j],
                                img_data[i + 1][j + 2], img_data[i + 2][j - 1], img_data[i + 2][j - 1]])

                u3 = np.mean(V10)

                # 特征二十
                point1 = np.mean(
                    [img_data[i - 2][j - 1], img_data[i - 1][j - 2], img_data[i][j - 1], img_data[i - 1][j]])
                point2 = np.mean(
                    [img_data[i - 1][j], img_data[i - 2][j + 1], img_data[i - 1][j + 2], img_data[i][j + 1]])
                point3 = np.mean(
                    [img_data[i + 1][j - 2], img_data[i][j - 1], img_data[i + 1][j], img_data[i + 2][j - 1]])
                point4 = np.mean(
                    [img_data[i + 1][j], img_data[i + 2][j + 1], img_data[i][j + 1], img_data[i + 1][j + 2]])
                Varr = np.array([v1, v2, v3, v4, point1, point2, point3, point4])
                temp1 = np.sign(Varr - img_data[i][j])
                temp = np.where(np.sign(Varr - img_data[i][j]) == -1)[0]
                temp1[temp] = 0

                # # 特征
                # 1。最大值
                f1 = np.max([v1, v2, v3, v4])
                # 2。最小值
                f2 = np.min([v1, v2, v3, v4])
                sod1 = abs(v2 + v4 + v5 + v12 - 4 * v1)
                sod2 = abs(v1 + v3 + v6 + v7 - 4 * v2)
                sod3 = abs(v2 + v4 + v8 + v9 - 4 * v3)
                sod4 = abs(v1 + v3 + v10 + v11 - 4 * v4)
                # 3。四个相邻像素二阶差的绝对值之和。使用对角拉普拉斯滤波器计算二阶差分，
                f3 = np.sum([sod1, sod2, sod3, sod4])
                f4_arr = [abs(v1 - v2), abs(v2 - v3), abs(v3 - v4), abs(v4 - v1)]
                # 4。四个相邻像素值之间的差值之和
                f4 = np.sum(f4_arr)
                # p2 = np.average([abs(v1 - v2), abs(v2 - v3), abs(v3 - v4), abs(v4 - v1)])
                p1 = (math.modf(np.average([v1, v2, v3, v4])))[0]
                p = np.ceil(np.average([v1, v2, v3, v4])) if p1 >= 0.5 else np.floor(np.average([v1, v2, v3, v4]))
                # f5_arr = [p2 - abs(v1 - v2), p2 - abs(v2 - v3), p2 - abs(v3 - v4), p2 - abs(v4 - v1)]
                # f5 = np.average(np.square(f5_arr))
                # f6_arr = [p - v1, p - v2, p - v3, p - v4]
                # f6 = np.average(np.square(f6_arr))
                # 5,水平竖直的点的差值和
                f5_arr = [abs(v6 - v7), abs(v5 - v2), abs(v2 - v8), abs(v1 - v3), abs(v12 - v4), abs(v4 - v9),
                          abs(v11 - v10), abs(v5 - v12), abs(v6 - v1), abs(v1 - v11), abs(v2 - v4), abs(v7 - v3),
                          abs(v3 - v10), abs(v8 - v9)]
                f5 = np.sum(f5_arr)
                # 5。四个相邻像素值之间差异的方差。
                new_f5 = np.sum(np.square(f4_arr - np.mean(f4_arr))) / 4
                # 6。像素点和周边12个像素的的差值和
                f6_arr = [abs(p - v1), abs(p - v2), abs(p - v3), abs(p - v4), abs(p - v5), abs(p - v6), abs(p - v7),
                          abs(p - v8), abs(p - v9), abs(p - v10), abs(p - v11), abs(p - v12)]
                f6 = np.sum(f6_arr)
                new_f6 = np.sum(np.squeeze(np.array([v1, v2, v3, v4]) - p)) / 4
                # 7。其相邻像素左侧梯度的大小之和
                f7 = np.sum(np.sqrt(np.sum(np.square(lg), axis=1)))
                # 8。其相邻像素右侧梯度的大小之和
                f8 = np.sum(np.sqrt(np.sum(np.square(rg), axis=1)))
                gradDiff = []
                gradDiff2 = []
                for s in range(3):
                    for q in range(s, 4):
                        gradDiff.append(lg[s] - lg[q])
                        gradDiff2.append(rg[s] - rg[q])
                # print(gradDiff, gradDiff2)
                gradDiff = np.array(gradDiff)
                gradDiff2 = np.array(gradDiff2)
                # 9.四个相邻像素左梯度之间差异的大小之和。
                f9 = np.sum(np.sqrt(np.sum(np.square(gradDiff), axis=1)))
                # 10.四个相邻像素右梯度之间差异的大小之和。
                f10 = np.sum(np.sqrt(np.sum(np.square(gradDiff2), axis=1)))
                # 11。sobel mask
                f11 = np.sqrt(v[i][j] ** 2 + h[i][j] ** 2)
                # 12。0，45，90，135度角
                f12 = np.sqrt(np.sum([t1, t2, t3, t4]))
                # 13。周边四个像素方差
                f13 = np.mean([v1, v2, v3, v4])
                # 14。以xn，m为中心的四个水平像素的局部方差计算：
                f14 = np.sum(x7arr - u1)
                # 15。以xn，m为中心的四个竖直像素的局部方差计算如下：
                f15 = np.sum(x8arr - u2)
                # 16。表示以xn，m为中心的5×5尺寸块的水平差和垂直差之和。
                f16 = np.sum([np.abs(Vu - Vb), np.abs(Hl - Hr)])
                # 17。12个点像素和其均值求差然后求和
                f17 = np.sum(np.abs(V10 - u3))
                # 18。45度梯度大小之和
                f18 = np.abs(img_data[i - 2][j + 1] - img_data[i - 1][j]) \
                      + np.abs(img_data[i - 1][j] - img_data[i][j - 1]) \
                      + np.abs(img_data[i][j - 1] - img_data[i + 1][j - 2]) \
                      + np.abs(img_data[i - 1][j + 2] - img_data[i][j - 1]) \
                      + np.abs(img_data[i][j - 1] - img_data[i + 1][j]) \
                      + np.abs(img_data[i + 1][j] - img_data[i + 2][j - 1])
                # 19。135度梯度大小之和
                f19 = np.abs(img_data[i - 2][j + 1] - img_data[i - 1][j]) \
                      + np.abs(img_data[i - 1][j] - img_data[i][j - 1]) \
                      + np.abs(img_data[i][j - 1] - img_data[i + 1][j - 2]) \
                      + np.abs(img_data[i - 1][j + 2] - img_data[i][j + 1]) \
                      + np.abs(img_data[i][j + 1] - img_data[i + 1][j]) \
                      + np.abs(img_data[i + 1][j] - img_data[i + 2][j - 1])
                # 20。由本地二进制模式（LBP）提取
                f20 = np.sum(temp1)

                fnew1 = np.var([v1, v2, v3, v4], ddof=0)
                temps = np.append([v2, v1, v4, v3], v2)
                fnew2 = np.var(abs(np.diff(temps)), ddof=0)


                # datakey = np.append(datakey,10)

                a = np.array(
                    [f1, f2, f4, f3, f10, f9, f8, f7, f5, f6, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20])

                # a = np.array([ f2, f4, f3, f10, f9, f8, f7, f5, f6])
                if i >= 4 and j >= 4:
                    w1 = 1 / (1 + abs(v[i][j]) + 2 * abs(v[i - 1][j]) + abs(v[i - 2][j]))
                    w2 = 1 / (1 + abs(v[i][j]) + 2 * abs(v[i + 1][j]) + abs(v[i + 2][j]))
                    w3 = 1 / (1 + abs(h[i][j]) + 2 * abs(h[i][j - 1]) + abs(h[i][j - 2]))
                    w4 = 1 / (1 + abs(h[i][j]) + 2 * abs(h[i][j + 1]) + abs(h[i][j + 2]))
                    warr = [w1 * v1, w2 * v3, w3 * v2, w4 * v4]
                    predx = np.round(np.sum(warr) / np.sum([w1, w2, w3, w4]))
                else:
                    predx = p
                test1[i][j] = p
                test2[i][j] = predx
                if np.mod(i + j, 2) == 0 and flag == 0:
                    # print(a)
                    prevalue = 0
                    F[:, index] = a
                    xmax = np.max([predx, p])
                    xmin = np.min([predx, p])
                    if xmax == xmin:
                        prevalue = xmin
                        typemap[i][j] = 1
                    elif img_data[i][j] <= xmin - 1:
                        prevalue = xmin
                        typemap[i][j] = 2
                    elif img_data[i][j] >= xmax:
                        prevalue = xmax
                        typemap[i][j] = 3
                    else:
                        typemap[i][j] = 4
                        # prevalue = img_data[i][j]
                    if i == 7 and j == 197:
                        print('此时的', prevalue, typemap[i][j], xmax, xmin, img_data[i][j])
                    # if prevalue == 0:
                    #     print('出错了1')
                    # errolist[index] = int(img_data[i][j]) - int(prevalue)
                    index += 1
                    if prevalue != 0:
                        erromap[i][j] = int(img_data[i][j]) - int(prevalue)

                if np.mod(i + j, 2) == 1 and flag == 1:
                    prevalue = 0
                    F[:, index] = a
                    xmax = np.max([predx, p])
                    xmin = np.min([predx, p])
                    if xmax == xmin:
                        prevalue = xmin
                        typemap[i][j] = 1
                    elif img_data[i][j] <= xmin - 1:
                        prevalue = xmin
                        typemap[i][j] = 2
                    elif img_data[i][j] >= xmax:
                        prevalue = xmax
                        typemap[i][j] = 3
                    else:
                        typemap[i][j] = 4
                    # else:
                    #     prevalue = img_data[i][j]
                    # if prevalue == 0:
                    #     print('出错了2')
                    # errolist[index] = int(img_data[i][j]) - int(prevalue)
                    index += 1
                    if prevalue != 0:
                        erromap[i][j] = int(img_data[i][j]) - int(prevalue)
    F = F[:, :index]
    print(datakey)
    datakey = np.array(datakey, dtype=int)
    F = F[datakey, :]
    pca = PCA(n_components=3)
    data = pca.fit_transform(F.T)
    data = np.array(data)
    # enter, u, u0, d, jm, p, fpc = cmeans(data.T, m=2, c=16, error=0.5, maxiter=10000)
    center, u, u0, d, jm, p, fpc = cmeans(data.T, 16, 2, error=0.00001, maxiter=100)
    label = np.argmax(u, axis=0)
    print('label', label)
    print(np.unique(label))
    return label, erromap, typemap, test1, test2


def  get_feature2(img_data, flag, ksize, v, h, complexs, key, bestkey):
    '''
    对图像的特征进行提取
    :param img_data: 图像信息
    :param flag: 奇数点还是偶数点
    :return:
    '''
    row, col = img_data.shape
    size = int((row * col) / 2)
    F = np.zeros((ksize, size))
    # 预测点
    predict = np.zeros((row, row))
    # 误差值
    erromap = np.ones((row, row)) * 999
    typemap = np.zeros((row, col))
    test1 = np.zeros((row, col))
    test2 = np.zeros((row, col))
    index = 0
    for i in range(2, row - 2):
        for j in range(2, col - 2):

            if complexs[i][j] < key:
                # 像素上下左右四个像素
                # 像素上下左右四个像素
                v1 = int(img_data[i - 1][j])
                v2 = int(img_data[i][j - 1])
                v3 = int(img_data[i + 1][j])
                v4 = int(img_data[i][j + 1])
                # 选中点
                x = int(img_data[i][j])
                # 其他九个点
                v5 = int(img_data[i - 2][j - 1])
                v6 = int(img_data[i - 1][j - 2])
                v7 = int(img_data[i + 1][j - 2])
                v8 = int(img_data[i + 2][j - 1])
                v9 = int(img_data[i + 2][j + 1])
                v10 = int(img_data[i + 1][j + 2])
                v11 = int(img_data[i - 1][j + 2])
                v12 = int(img_data[i - 2][j + 1])
                # 左梯度和右梯度
                lg = np.array([[v5 - v1, v2 - v1], [v1 - v4, v3 - v4], [v2 - v3, v8 - v3], [v6 - v2, v7 - v2]])
                rg = np.array([[v12 - v1, v4 - v1], [v11 - v4, v10 - v4], [v4 - v3, v9 - v3], [v1 - v2, v3 - v2]])

                # 从特征11开始为wang以外的特征
                t0 = np.array(
                    [int(img_data[i][j - 1]), int(img_data[i][j + 1]),
                     np.round(int(img_data[i][j - 1] + img_data[i][j + 1]) / 2)])
                t45 = np.array(
                    [img_data[i][j + 1], img_data[i + 1][j],
                     np.round(int(img_data[i][j + 1] + img_data[i + 1][j]) / 2)])
                t90 = np.array(
                    [img_data[i + 1][j], img_data[i - 1][j],
                     np.round(int(img_data[i + 1][j] + img_data[i - 1][j]) / 2)])
                t135 = np.array(
                    [img_data[i][j - 1], img_data[i + 1][j],
                     np.round(int(img_data[i][j - 1] + img_data[i + 1][j]) / 2)])
                u = np.mean([int(img_data[i][j - 1] + img_data[i][j + 1]) / 2,
                             int(img_data[i][j + 1] + img_data[i + 1][j]) / 2,
                             int(img_data[i + 1][j] + img_data[i - 1][j]) / 2,
                             int(img_data[i][j - 1] + img_data[i + 1][j]) / 2])
                t1 = np.sum(np.square(t0 - u))
                t2 = np.sum(np.square(t45 - u))
                t3 = np.sum(np.square(t90 - u))
                t4 = np.sum(np.square(t135 - u))

                # 特征14
                if j - 3 > 0 and j + 3 < 511:
                    x7arr = np.array([img_data[i][j - 3], img_data[i][j - 1], img_data[i][j + 1], img_data[i][j + 3]])
                else:
                    x7arr = np.array([img_data[i][j - 1], img_data[i][j + 1]])
                u1 = np.mean(x7arr)
                # 特征15
                if i - 3 > 0 and i + 3 < 511:
                    x8arr = np.array([img_data[i - 3][j], img_data[i - 1][j], img_data[i + 1][j], img_data[i + 3][j]])
                else:
                    x8arr = np.array([img_data[i - 1][j], img_data[i + 1][j]])
                u2 = np.mean(x8arr)
                # 特征16
                Vu = np.array([img_data[i - 1][j - 2], img_data[i - 2][j - 1], img_data[i][j - 1],
                               img_data[i - 1][j], img_data[i - 2][j + 1], img_data[i][j + 1],
                               img_data[i - 1][j + 2]]
                              )
                Vb = np.array([img_data[i + 1][j - 2], img_data[i][j - 1], img_data[i + 2][j - 1],
                               img_data[i + 1][j], img_data[i][j + 1], img_data[i + 2][j + 1],
                               img_data[i + 1][j + 2]]
                              )
                Hl = np.array([img_data[i - 2][j - 1], img_data[i - 1][j - 2], img_data[i - 1][j],
                               img_data[i][j - 1], img_data[i + 1][j - 2], img_data[i + 1][j],
                               img_data[i + 2][j - 1]]
                              )
                Hr = np.array([img_data[i - 2][j + 1], img_data[i - 1][j], img_data[i - 1][j + 2],
                               img_data[i][j + 1], img_data[i + 1][j], img_data[i + 1][j + 2],
                               img_data[i + 2][j + 1]]
                              )
                # 特征17
                V10 = np.array([img_data[i - 2][j - 1], img_data[i - 2][j + 1], img_data[i - 1][j - 2],
                                img_data[i - 1][j], img_data[i - 1][j + 2], img_data[i][j - 1],
                                img_data[i][j + 1], img_data[i + 1][j - 2], img_data[i + 1][j],
                                img_data[i + 1][j + 2], img_data[i + 2][j - 1], img_data[i + 2][j - 1]])

                u3 = np.mean(V10)

                # 特征二十
                point1 = np.mean(
                    [img_data[i - 2][j - 1], img_data[i - 1][j - 2], img_data[i][j - 1], img_data[i - 1][j]])
                point2 = np.mean(
                    [img_data[i - 1][j], img_data[i - 2][j + 1], img_data[i - 1][j + 2], img_data[i][j + 1]])
                point3 = np.mean(
                    [img_data[i + 1][j - 2], img_data[i][j - 1], img_data[i + 1][j], img_data[i + 2][j - 1]])
                point4 = np.mean(
                    [img_data[i + 1][j], img_data[i + 2][j + 1], img_data[i][j + 1], img_data[i + 1][j + 2]])
                Varr = np.array([v1, v2, v3, v4, point1, point2, point3, point4])
                temp1 = np.sign(Varr - img_data[i][j])
                temp = np.where(np.sign(Varr - img_data[i][j]) == -1)[0]
                temp1[temp] = 0

                # # 特征

                # 2。最小值
                f2 = np.min([v1, v2, v3, v4])

                f4_arr = [abs(v1 - v2), abs(v2 - v3), abs(v3 - v4), abs(v4 - v1)]
                # 4。四个相邻像素值之间的差值之和
                f4 = np.sum(f4_arr)
                # p2 = np.average([abs(v1 - v2), abs(v2 - v3), abs(v3 - v4), abs(v4 - v1)])
                p1 = (math.modf(np.average([v1, v2, v3, v4])))[0]
                p = np.ceil(np.average([v1, v2, v3, v4])) if p1 >= 0.5 else np.floor(np.average([v1, v2, v3, v4]))

                gradDiff = []
                gradDiff2 = []
                for s in range(3):
                    for q in range(s, 4):
                        gradDiff.append(lg[s] - lg[q])
                        gradDiff2.append(rg[s] - rg[q])
                # print(gradDiff, gradDiff2)
                gradDiff = np.array(gradDiff)
                gradDiff2 = np.array(gradDiff2)
                # 9.四个相邻像素左梯度之间差异的大小之和。
                f9 = np.sum(np.sqrt(np.sum(np.square(gradDiff), axis=1)))
                # 10.四个相邻像素右梯度之间差异的大小之和。
                f10 = np.sum(np.sqrt(np.sum(np.square(gradDiff2), axis=1)))
                # 11。sobel mask




                a = np.array([f10,f9,f2,f4])
                # a = np.array([ f2, f4, f3, f10, f9, f8, f7, f5, f6])
                if i >= 4 and j >= 4:
                    w1 = 1 / (1 + abs(v[i][j]) + 2 * abs(v[i - 1][j]) + abs(v[i - 2][j]))
                    w2 = 1 / (1 + abs(v[i][j]) + 2 * abs(v[i + 1][j]) + abs(v[i + 2][j]))
                    w3 = 1 / (1 + abs(h[i][j]) + 2 * abs(h[i][j - 1]) + abs(h[i][j - 2]))
                    w4 = 1 / (1 + abs(h[i][j]) + 2 * abs(h[i][j + 1]) + abs(h[i][j + 2]))
                    warr = [w1 * v1, w2 * v3, w3 * v2, w4 * v4]
                    predx = np.round(np.sum(warr) / np.sum([w1, w2, w3, w4]))
                else:
                    predx = p
                test1[i][j] = p
                test2[i][j] = predx
                if np.mod(i + j, 2) == 0 and flag == 0:
                    # print(a)
                    prevalue = 0
                    F[:, index] = a
                    xmax = np.max([predx, p])
                    xmin = np.min([predx, p])
                    if xmax == xmin:
                        prevalue = xmin
                        typemap[i][j] = 1
                    elif img_data[i][j] <= xmin - 1:
                        prevalue = xmin
                        typemap[i][j] = 2
                    elif img_data[i][j] >= xmax:
                        prevalue = xmax
                        typemap[i][j] = 3
                    else:
                        typemap[i][j] = 4
                        # prevalue = img_data[i][j]
                    index += 1
                    if prevalue != 0:
                        erromap[i][j] = int(img_data[i][j]) - int(prevalue)

                if np.mod(i + j, 2) == 1 and flag == 1:
                    prevalue = 0
                    F[:, index] = a
                    xmax = np.max([predx, p])
                    xmin = np.min([predx, p])
                    if xmax == xmin:
                        prevalue = xmin
                        typemap[i][j] = 1
                    elif img_data[i][j] <= xmin - 1:
                        prevalue = xmin
                        typemap[i][j] = 2
                    elif img_data[i][j] >= xmax:
                        prevalue = xmax
                        typemap[i][j] = 3
                    else:
                        typemap[i][j] = 4
                    # else:
                    #     prevalue = img_data[i][j]
                    # if prevalue == 0:
                    #     print('出错了2')
                    # errolist[index] = int(img_data[i][j]) - int(prevalue)
                    index += 1
                    if prevalue != 0:
                        erromap[i][j] = int(img_data[i][j]) - int(prevalue)
    F = F[:, :index]
    pca = PCA(n_components=3)
    data = pca.fit_transform(F.T)
    data = np.array(data)
    # enter, u, u0, d, jm, p, fpc = cmeans(data.T, m=2, c=16, error=0.5, maxiter=10000)
    center, u, u0, d, jm, p, fpc = cmeans(data.T, 16, 2, error=0.00001, maxiter=100)
    label = np.argmax(u, axis=0)
    print('label', label)
    print(np.unique(label))
    return label, erromap, typemap, test1, test2


def get_grad(img_data):
    '''
    对图像的特征进行提取
    :param img_data: 图像信息
    :param flag: 奇数点还是偶数点
    :return:
    '''
    row, col = img_data.shape
    size = int((row * col) / 2)

    v = np.zeros((row, col))
    h = np.zeros((row, col))
    for i in range(2, row - 2):
        for j in range(2, col - 2):
            # 像素上下左右四个像素
            v1 = int(img_data[i - 1][j])
            v2 = int(img_data[i][j - 1])
            v3 = int(img_data[i + 1][j])
            v4 = int(img_data[i][j + 1])
            # 选中点
            x = int(img_data[i][j])
            # 其他九个点
            v5 = int(img_data[i - 2][j - 1])
            v6 = int(img_data[i - 1][j - 2])
            v7 = int(img_data[i + 1][j - 2])
            v8 = int(img_data[i + 2][j - 1])
            v9 = int(img_data[i + 2][j + 1])
            v10 = int(img_data[i + 1][j + 2])
            v11 = int(img_data[i - 1][j + 2])
            v12 = int(img_data[i - 2][j + 1])

            if np.mod(i + j, 2) == 1:
                # 新点
                x1 = int(img_data[i + 1][j + 1])
                x2 = int(img_data[i + 1][j - 1])
                x3 = int(img_data[i - 1][j + 1])
                x4 = int(img_data[i + 1][j - 1])
                x5 = int(img_data[i][j + 2])
                x6 = int(img_data[i][j - 2])
                h[i][j] = np.round((6 * np.sum([x1 - x2, x3 - x4]) + 2 * np.sum([x5 - x6])) / 4)
                y1 = int(img_data[i + 1][j + 1])
                y2 = int(img_data[i - 1][j + 1])
                y3 = int(img_data[i + 1][j - 1])
                y4 = int(img_data[i - 1][j - 1])
                y5 = int(img_data[i + 2][j])
                y6 = int(img_data[i - 2][j])
                # y7 = int(img_data[i-2][j-1])
                # y9 = int(img_data[i-2][j-2])
                # y10 = int(img_data[i-2][j+2])

                v[i][j] = np.round((6 * np.sum([y1 - y2, y3 - y4]) + 2 * np.sum([y5 - y6])) / 4)
                # if i -3<0:
                #     v[i-1][j] =np.round((5*(y7+v12)+2*v1)/3+(3*(v2+v4)+v1+v3)/2)
                # if i-3>=0:
                #     y8 = int(img_data[i-3][j])
                #     y11 =int(img_data[i-3][j+1])
                #     y12 = int(img_data[i-3][j-1])
                #     v1 = np.round((6*np.sum([v4-v12,v2-y7])+2*np.sum(v3-y8))/4)
                #
                # else:
                #     v1 =np.round((5*(y7+v12)+2*v1)/3+(3*(v2+v4)+v1+v3)/2)
                # if i-4>=0:
                #     y11 = int(img_data[i - 3][j + 1])
                #     y12 = int(img_data[i - 3][j - 1])
                #     y13 = int(img_data[i-4][j])
                #     v3 = np.round((6 * np.sum([v12 - y11, y7 - y12]) + 2 * (y10 - y9)) / 4)

            if np.mod(i + j, 2) == 0:
                y1 = int(img_data[i + 2][j + 1])
                y2 = int(img_data[i + 2][j - 1])
                y3 = int(img_data[i - 2][j + 1])
                y4 = int(img_data[i + 2][j - 1])
                y5 = int(img_data[i + 1][j + 2])
                y6 = int(img_data[i + 1][j - 2])
                y7 = int(img_data[i - 1][j + 2])
                y8 = int(img_data[i - 1][j - 2])
                y9 = int(img_data[i][j + 1])
                y10 = int(img_data[i][j - 1])
                h[i][j] = np.round(
                    (np.sum([y1 - y2, y3 - y4]) + np.sum([y5 - y6, y7 - y8]) + 10 * np.sum([y9 - y10])) / 4)
                y1 = int(img_data[i + 1][j + 2])
                y2 = int(img_data[i - 1][j + 2])
                y3 = int(img_data[i + 1][j - 2])
                y4 = int(img_data[i - 1][j - 2])
                y5 = int(img_data[i + 2][j + 1])
                y6 = int(img_data[i - 2][j + 1])
                y7 = int(img_data[i + 2][j - 1])
                y8 = int(img_data[i - 2][j - 1])
                y9 = int(img_data[i + 1][j])
                y10 = int(img_data[i - 1][j])
                v[i][j] = np.round(
                    (np.sum([y1 - y2, y3 - y4]) + np.sum([y5 - y6, y7 - y8]) + 10 * np.sum([y9 - y10])) / 4)

            # if flag == 1:
            #     if np.mod(i + j, 2) == 1:
            #         # 新点
            #         x1 = int(img_data[i + 1][j + 1])
            #         x2 = int(img_data[i + 1][j - 1])
            #         x3 = int(img_data[i - 1][j + 1])
            #         x4 = int(img_data[i + 1][j - 1])
            #         x5 = int(img_data[i][j + 2])
            #         x6 = int(img_data[i][j - 2])
            #         h = np.round((6 * np.sum([x1 - x2, x3 - x4]) + 2 * np.sum([x5 - x6])) / 4)
            #         x1 = int(img_data[i + 1][j + 1])
            #         x2 = int(img_data[i - 1][j + 1])
            #         x3 = int(img_data[i + 1][j - 1])
            #         x4 = int(img_data[i - 1][j - 1])
            #         x5 = int(img_data[i + 2][j])
            #         x6 = int(img_data[i - 2][j])
            #         v[i][j] = np.round((6 * np.sum([x1 - x2, x3 - x4]) + 2 * np.sum([x5 - x6])) / 4)
            #     if np.mod(i + j, 2) == 0:
            #         y1 = int(img_data[i + 2][j + 1])
            #         y2 = int(img_data[i + 2][j - 1])
            #         y3 = int(img_data[i - 2][j + 1])
            #         y4 = int(img_data[i + 2][j - 1])
            #         y5 = int(img_data[i + 1][j + 2])
            #         y6 = int(img_data[i + 1][j - 2])
            #         y7 = int(img_data[i - 1][j + 2])
            #         y8 = int(img_data[i - 1][j - 2])
            #         y9 = int(img_data[i][j + 1])
            #         y10 = int(img_data[i][j - 1])
            #         h[i][j] = np.round((np.sum([y1 - y2, y3 - y4]) + np.sum([y5 - y6, y7 - y8]) + 10 * np.sum([y9 - y10])) / 4)
            #         y1 = int(img_data[i + 1][j + 2])
            #         y2 = int(img_data[i - 1][j + 2])
            #         y3 = int(img_data[i + 1][j - 2])
            #         y4 = int(img_data[i - 1][j - 2])
            #         y5 = int(img_data[i + 2][j + 1])
            #         y6 = int(img_data[i - 2][j + 1])
            #         y7 = int(img_data[i + 2][j - 1])
            #         y8 = int(img_data[i - 2][j - 1])
            #         y9 = int(img_data[i + 1][j])
            #         y10 = int(img_data[i - 1][j])
            #         v = np.round((np.sum([y1 - y2, y3 - y4]) + np.sum([y5 - y6, y7 - y8]) + 10 * np.sum([y9 - y10])) / 4)

    return v, h


def complexity_map(img_data, label, flags, complexs, key):
    cm = np.ones(img_data.shape) * 999
    A, B = img_data.shape
    count = 0
    for i in range(2, A - 2):
        for j in range(2, B - 2):
            if complexs[i][j] < key:
                if np.mod(i + j, 2) == 0 and flags == 0:
                    cm[i][j] = int(label[count])
                    count = count + 1
                if np.mod(i + j, 2) == 1 and flags == 1:
                    if count == 49969:
                        print([i, j])
                        print(label[count])
                    cm[i][j] = int(label[count])
                    count = count + 1

    print(count)
    return cm


def cal_entropy(imgs, label, ks, flags, em, complexs, key):
    A, B = imgs.shape
    his = []
    count = 0
    entropy = []
    for i in range(ks):
        his.append([])
    for i in range(2, A - 2):
        for j in range(2, B - 2):
            if complexs[i][j] < key:
                v1 = int(imgs[i - 1][j])
                v2 = int(imgs[i + 1][j])
                v3 = int(imgs[i][j + 1])
                v4 = int(imgs[i][j - 1])
                p1 = (math.modf(np.average([v1, v2, v3, v4])))[0]
                p = np.ceil(np.average([v1, v2, v3, v4])) if p1 >= 0.5 else np.floor(np.average([v1, v2, v3, v4]))
                e = int(imgs[i][j]) - p

                if flags == 0 and np.mod(i + j, 2) == 0:
                    his[label[count]].append(em[i][j])
                    count = count + 1
                elif flags == 1 and np.mod(i + j, 2) == 1:
                    his[label[count]].append(em[i][j])
                    count = count + 1

    for i in range(ks):
        e = 0
        c = Counter(his[i])
        total = len(his[i])
        for j in c.values():
            pro = int(j) / total
            e = e + pro * math.log(1 / pro, 2)
        entropy.append(e)
    print(entropy)
    entropy_sort = sorted(entropy);
    cor = []
    labels = []
    print(entropy_sort)
    print('权值总和', (entropy_sort / np.sum(entropy_sort)) * 100)
    for i in range(ks):
        for j in range(ks):
            if entropy[i] == entropy_sort[j]:
                cor.append(j)
                entropy_sort[j] = -1
                break
    print(cor)
    for i in label:
        labels.append(cor[i])
    # legend = []
    # fig = []
    # frequency = list(range(ks))
    # new_name = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p']
    # for i in range(ks):
    #     legend.append('l=' + str(cor[i]))
    #     fig.append(str(cor[i]))
    #     # print(len(his[i]))
    #     frequency[cor[i]] = int(len(his[cor[i]]))
    # plt.grid(ls=':');
    # plt.bar(range(ks), frequency, tick_label=new_name, color='b');
    # plt.title('The distribution of pixels');
    # plt.xlabel('Neuron')
    # plt.ylabel('Population');
    # plt.show()
    return labels, cor


def cal_aux(checklist, data_length, scale, re, lcm, flags):
    cl = 0
    test = []
    for i in range(16):
        test.append(i)
    checklist = np.array(checklist) + 1
    # checklist = np.array(test)+1
    print('incheck', checklist)
    # a = np.ceil(np.log2(np.max(checklist)))
    if flags == 0:
        for i in range(16):
            #
            if re[i] == 250:
                scale = scale - 1
            if checklist[i] != i:
                cl = cl + np.ceil(np.log2(checklist[i]))
        if np.sum(lcm) == 0:
            aux = scale * 3 + 4 + 1 + 17 + cl + 4
        else:
            aux = scale * 3 + 4 + 1 + data_length * 8 + 17 + 17 + cl + 4
    if flags == 1:  # 根据寻优的bins更新辅助信息的长度
        for i in range(16):
            if re[i] < 250 and checklist[i] > i:
                cl = cl + np.ceil(np.log2(checklist[i]))
            if re[i] == 250:
                scale = scale - 1
                print('scale', scale)
        if np.sum(lcm) == 0:
            aux = scale * 3 + 4 + 1 + 17 + cl + 4
        else:
            aux = scale * 3 + 4 + 1 + data_length * 8 + 17 + 17 + cl + 4
    print('The aux is ', flags, ' ', aux)
    return aux


def re_hs(k, row, col, cm, flag, em, complexs, key):
    Hs = np.zeros((511, k))
    # index = 0
    for i in range(2, row - 2):
        for j in range(2, col - 2):
            if int(cm[i][j]) != 999:
                if np.mod(i + j, 2) == 0 and flag == 0 and complexs[i][j] < key:
                    if em[i][j] != 999:
                        Hs[int(em[i][j] + 255)][int(cm[i][j])] += 1
                    # index += 1
                if np.mod(i + j, 2) == 1 and flag == 1 and complexs[i][j] < key:
                    if em[i][j] != 999:
                        Hs[int(em[i][j] + 255)][int(cm[i][j])] += 1
                    # index += 1
    return Hs


def insert_msg(em, cm, bin, img_hide3, secret, ec3, flag3):
    '''
        em误差矩阵
        Dbis复杂度矩阵
        bin最佳区间
        img_hide图形矩阵
        secret嵌入矩阵
        插入需要插入的信息
    '''
    index = 0
    index2 = 0
    row, col = img_hide3.shape
    for i in range(2, row - 2):
        for j in range(2, col - 2):
            if np.mod(i + j, 2) == 0 and flag3 == 0 and ec3 > 0:
                ks = cm[i][j] - 1
                if em[i][j] == bin[int(ks)]:
                    ec3 = ec3 - 1
                    img_hide3[i][j] += secret[i][j]
                    if secret[i][j] == 1:
                        index2 += 1
                if em[i][j] == -bin[int(ks)] - 1:
                    ec3 = ec3 - 1
                    img_hide3[i][j] -= secret[i][j]
                    if secret[i][j] == 1:
                        index2 += 1
                if em[i][j] > bin[int(ks)]:
                    img_hide3[i][j] += 1
                    index += 1
                if em[i][j] < -bin[int(ks)] - 1:
                    img_hide3[i][j] -= 1
                    index += 1
            if np.mod(i + j, 2) == 1 and flag3 == 1 and ec3 > 0:
                ks = cm[i][j] - 1
                if em[i][j] == bin[int(ks)]:
                    ec3 = ec3 - 1
                    img_hide3[i][j] += secret[i][j]
                    if secret[i][j] == 1:
                        index2 += 1
                if em[i][j] == -bin[int(ks)] - 1:
                    ec3 = ec3 - 1
                    img_hide3[i][j] -= secret[i][j]
                    if secret[i][j] == 1:
                        index2 += 1
                if em[i][j] > bin[int(ks)]:
                    img_hide3[i][j] += 1
                    index += 1
                if em[i][j] < -bin[int(ks)] - 1:
                    img_hide3[i][j] -= 1
                    index += 1

    print("偏移数量", index)
    print('偏移点数量', index2)
    return img_hide3, ec3


def instert_ms(em, cm, img_hide3, secret, RateList, flag3, PZlist, typemap, ec):
    row, col = img_hide3.shape
    index = 0
    index2 = 0
    indextest = 0
    secretinfo = np.zeros(row * col)
    for i in range(2, row - 2):
        for j in range(2, col - 2):
            m = int(cm[i][j])
            types = 0
            if m != 999:
                if RateList[m] != 0:
                    P = np.array(PZlist[m][0])
                    Z = np.array(PZlist[m][1])
                    types = 1
                else:
                    types = 0

            if np.mod(i + j, 2) == 0 and flag3 == 0 and types == 1 and typemap[i][j] != 4:

                leftindex = np.where(P < 255)[0]
                rightindex = np.where(P > 254)[0]
                # print('index',leftindex,rightindex)
                if len(leftindex) > 0:
                    Pleft = P[:leftindex[-1] + 1]
                    Zleft = Z[:leftindex[-1] + 1]
                    for k in range(len(Pleft) - 1, -1, -1):
                        # if em[i][j] == (P[k]-255):
                        #     img_hide3[i][j] +=secret[i][j]
                        #     ec3-=1
                        # tmp = img_hide3[i][].copy()
                        if Pleft[k] > Zleft[k] and RateList[m] > 0 and ec > 0:
                            # if em[index] == (P[k] - 255):
                            # if typemap[i][j] == 3:
                            #     print('zhege',em[i][j],P[k],Z[k])
                            #     print('101123')
                            if em[i][j] == (Pleft[k] - 255) and RateList[m] > 0 and ec > 0:
                                img_hide3[i][j] -= secret[i][j]
                                secretinfo[index] = secret[i][j]
                                RateList[m] -= 1
                                ec -= 1
                                index += 1

                                # print('此时1', secret[i][j])
                            if em[i][j] > (Zleft[k] - 255) and em[i][j] < (Pleft[k] - 255):
                                # if em[index]  > (Z[k] - 255) and em[index]  < (P[k] - 255):
                                img_hide3[i][j] -= 1
                                index2 += 1
                                # index += 1
                if len(rightindex) > 0:
                    Pright = P[rightindex[0]:]
                    Zright = Z[rightindex[0]:]
                    for k in range(len(Pright)):
                        # print('此时pPright[k]', Pright[k])
                        if Pright[k] < Zright[k] and RateList[m] > 0 and ec > 0:
                            if em[i][j] == (Pright[k] - 255) and RateList[m] > 0 and ec > 0:
                                # if em[index]  == (P[k] - 255):
                                img_hide3[i][j] += secret[i][j]
                                secretinfo[index] = secret[i][j]
                                # print('此时2',secret[i][j])
                                RateList[m] -= 1
                                ec -= 1
                                index += 1
                            if em[i][j] < (Zright[k] - 255) and em[i][j] > (Pright[k] - 255):
                                # if em[index] < (Z[k] - 255) and em[index]> (P[k] - 255):
                                img_hide3[i][j] += 1
                                index2 += 1
                # print('left',Pleft,Pright)

                # index += 1
            if np.mod(i + j, 2) == 1 and flag3 == 1 and types == 1 and typemap[i][j] != 4:

                leftindex = np.where(P < 255)[0]
                rightindex = np.where(P > 254)[0]
                # print('index',leftindex,rightindex)
                if len(leftindex) > 0:
                    Pleft = P[:leftindex[-1] + 1]
                    Zleft = Z[:leftindex[-1] + 1]
                    for k in range(len(Pleft) - 1, -1, -1):
                        # if em[i][j] == (P[k]-255):
                        #     img_hide3[i][j] +=secret[i][j]
                        #     ec3-=1
                        # tmp = img_hide3[i][].copy()
                        if Pleft[k] > Zleft[k] and RateList[m] > 0 and ec > 0:
                            # if em[index] == (P[k] - 255):
                            # if typemap[i][j] == 3:
                            #     print('zhege',em[i][j],P[k],Z[k])
                            #     print('101123')
                            if em[i][j] == (Pleft[k] - 255) and RateList[m] > 0 and ec > 0:
                                img_hide3[i][j] -= secret[i][j]
                                secretinfo[index] = secret[i][j]
                                RateList[m] -= 1
                                ec -= 1
                                index += 1

                                # print('此时1', secret[i][j])
                            if em[i][j] > (Zleft[k] - 255) and em[i][j] < (Pleft[k] - 255):
                                # if em[index]  > (Z[k] - 255) and em[index]  < (P[k] - 255):
                                img_hide3[i][j] -= 1
                                index2 += 1
                                # index += 1
                if len(rightindex) > 0:
                    Pright = P[rightindex[0]:]
                    Zright = Z[rightindex[0]:]
                    for k in range(len(Pright)):
                        # print('此时pPright[k]', Pright[k])
                        if Pright[k] < Zright[k] and RateList[m] > 0 and ec > 0:
                            if em[i][j] == (Pright[k] - 255) and RateList[m] > 0 and ec > 0:
                                # if em[index]  == (P[k] - 255):
                                img_hide3[i][j] += secret[i][j]
                                secretinfo[index] = secret[i][j]
                                # print('此时2',secret[i][j])
                                RateList[m] -= 1
                                ec -= 1
                                index += 1
                            if em[i][j] < (Zright[k] - 255) and em[i][j] > (Pright[k] - 255):
                                # if em[index] < (Z[k] - 255) and em[index]> (P[k] - 255):
                                img_hide3[i][j] += 1
                                index2 += 1
                # print('left',Pleft,Pright)
                # index += 1
    print('嵌入总数', index)
    print('造成失真', index2)
    print('indextest', indextest)
    secretinfo = secretinfo[:index]
    return img_hide3, RateList, secretinfo, ec


def ga_searchbin(H, rate):
    T = 300
    G = 100
    maxL = 25
    V, USE = initpopulation(H, maxL, G)
    R, D, Layer = caculateRD(V, maxL, G, H)

    Best_V, Best_dist, feature = find_best(R, D, G, rate, maxL, V)

    Best_V, D, t_D, features = divide_rate(T, G, V, maxL, H, USE, rate, Best_V, feature, Best_dist)

    S_Rate, S_dist, PzList = Choose_PZ(Best_V, H, maxL)

    return S_Rate, S_dist, PzList


def getModifyMap(PzList):
    PZ = []
    for k in range(len(PzList)):
        if len(PzList[k][0]) != 0:
            P = PzList[k][0]
            Z = PzList[k][1]
            P = np.sort(P)
            Z = np.sort(Z)
            for i in range(len(P)):
                for j in range(len(P)):
                    if P[i] < Z[i]:
                        if P[i] + 1 <= Z[i] - 1:
                            if P[i] < P[j] < Z[i]:
                                P[j] += 1
                                Z[j] += 1
                    else:
                        if P[i] - 1 >= Z[i] + 1:
                            if P[i] > P[j] > Z[i]:
                                P[j] -= 1
                                Z[j] -= 1
            PZ.append([P, Z])
        else:
            PZ.append([[], []])
    return PZ


def danci(danci_img, flags, ks, ecfinals, key, bestkey,v,h,datakey):
    danci_img, lcm, halfsize, data = Over_flow(danci_img, flags)
    # 数组长度
    data_length = len(data)
    # 获取图片的坐标的长宽
    row, col = danci_img.shape
    # 初始图像数据,获取误差以及按照图像的复杂度进行分类

    complexs, complexs2 = get_complex_map(danci_img, flags)
    print('最大', np.max(complexs2))
    label, em, typemap, test1, test2 = get_feature(danci_img, flags, 20, v, h, complexs, key, bestkey,datakey)
    label, check = cal_entropy(danci_img, label, ks, flags, em, complexs, key)
    label = np.array(label)
    labelindex = np.where(label == 0)[0]
    # print(labelindex)
    # complexdata = complexs2[labelindex]
    cm = complexity_map(danci_img, label, flags, complexs, key)
    hs = re_hs(16, row, col, cm, flags, em, complexs, key)
    # check = cal_entropy(hs, ks)
    R = np.zeros(16)
    anx = cal_aux(check, data_length, ks, R, lcm, flags)
    # anx = test[0]
    ec1 = np.ceil(ecfinals / 2)
    print('ec1', ec1)
    hs = hs.T
    S_Rate, S_dist, PzList = ga_searchbin(hs, ec1)
    print('此时最佳', S_Rate)
    Rates = S_Rate.copy()
    print('最佳选点', PzList)
    # PzList = getModifyMap(PzList)
    # # img_hide记录修改过后的图像坐标
    img_hide1 = copy.deepcopy(danci_img)
    # # 嵌入的数据secrt_msg[0][index]
    secret_info = secret_msg(row, col)
    # # 嵌入数据之后的误差图像
    img_hide1, RateList, secretinfos, ec1 = instert_ms(em, cm, img_hide1, secret_info, S_Rate, flags, PzList, typemap,
                                                       ec1)
    # # lsb插入辅助信息
    anx_secret = secret_msg(row, col)
    img_hide1 = Lsb_insert(row, col, anx, img_hide1, flags, anx_secret)
    # return img_hide1, RateList, secretinfos, cm, PzList, Rates, ec1, em, typemap, test1, test2, v, h, secret_info
    return img_hide1, RateList, ec1


def plt_make(x, psnr):
    # x = np.array([0.0267, 0.05, 0.1, 0.20, 0.3, 0.40, 0.499, 0.60, 0.7])
    y = psnr
    plt.plot(x, y, '-r', label='psnr')
    plt.plot(x, y, '.b')
    plt.title('lena psnr')
    plt.xlabel('ec', color='#1C2833')
    plt.ylabel('psnr', color='#1C2833')
    plt.legend(loc='upper left')
    plt.grid()
    plt.show()


def get_em(img_data, flag, v, h):
    row, col = img_data.shape
    size = int((row * col) / 2)
    # 预测点
    predict = np.zeros((row, row))
    # 误差值
    erromap = np.ones((row, col)) * 999
    index = 0
    typemap = np.zeros((row, col))
    test1 = np.zeros((row, col))
    test2 = np.zeros((row, col))
    for i in range(2, row - 2):
        for j in range(2, col - 2):
            # 像素上下左右四个像素
            v1 = int(img_data[i - 1][j])
            v2 = int(img_data[i][j - 1])
            v3 = int(img_data[i + 1][j])
            v4 = int(img_data[i][j + 1])
            # 选中点
            x = int(img_data[i][j])
            # 其他九个点
            v5 = int(img_data[i - 2][j - 1])
            v6 = int(img_data[i - 1][j - 2])
            v7 = int(img_data[i + 1][j - 2])
            v8 = int(img_data[i + 2][j - 1])
            v9 = int(img_data[i + 2][j + 1])
            v10 = int(img_data[i + 1][j + 2])
            v11 = int(img_data[i - 1][j + 2])
            v12 = int(img_data[i - 2][j + 1])
            # 左梯度和右梯度
            lg = np.array([[v5 - v1, v2 - v1], [v1 - v4, v3 - v4], [v2 - v3, v8 - v3], [v6 - v2, v7 - v2]])
            rg = np.array([[v12 - v1, v4 - v1], [v11 - v4, v10 - v4], [v4 - v3, v9 - v3], [v1 - v2, v3 - v2]])
            # # 特征
            f1 = np.max([v1, v2, v3, v4])
            f2 = np.min([v1, v2, v3, v4])
            sod1 = abs(v2 + v4 + v5 + v12 - 4 * v1)
            sod2 = abs(v1 + v3 + v6 + v7 - 4 * v2)
            sod3 = abs(v2 + v4 + v8 + v9 - 4 * v3)
            sod4 = abs(v1 + v3 + v10 + v11 - 4 * v4)
            f3 = np.sum([sod1, sod2, sod3, sod4])
            f4_arr = [abs(v1 - v2), abs(v2 - v3), abs(v3 - v4), abs(v4 - v1)]
            f4 = np.sum(f4_arr)
            # p2 = np.average([abs(v1 - v2), abs(v2 - v3), abs(v3 - v4), abs(v4 - v1)])
            p1 = (math.modf(np.average([v1, v2, v3, v4])))[0]
            p = np.ceil(np.average([v1, v2, v3, v4])) if p1 >= 0.5 else np.floor(np.average([v1, v2, v3, v4]))
            # f5_arr = [p2 - abs(v1 - v2), p2 - abs(v2 - v3), p2 - abs(v3 - v4), p2 - abs(v4 - v1)]
            # f5 = np.average(np.square(f5_arr))
            # f6_arr = [p - v1, p - v2, p - v3, p - v4]
            # f6 = np.average(np.square(f6_arr))
            f5_arr = [abs(v6 - v7), abs(v5 - v2), abs(v2 - v8), abs(v1 - v3), abs(v12 - v4), abs(v4 - v9),
                      abs(v11 - v10), abs(v5 - v12), abs(v6 - v1), abs(v1 - v11), abs(v2 - v4), abs(v7 - v3),
                      abs(v3 - v10), abs(v8 - v9)]
            f5 = np.sum(f5_arr)
            f6_arr = [abs(p - v1), abs(p - v2), abs(p - v3), abs(p - v4), abs(p - v5), abs(p - v6), abs(p - v7),
                      abs(p - v8), abs(p - v9), abs(p - v10), abs(p - v11), abs(p - v12)]
            f6 = np.sum(f6_arr)
            f7 = np.sum(np.sqrt(np.sum(np.square(lg), axis=1)))
            f8 = np.sum(np.sqrt(np.sum(np.square(rg), axis=1)))
            gradDiff = []
            gradDiff2 = []
            for s in range(3):
                for q in range(s, 4):
                    gradDiff.append(lg[s] - lg[q])
                    gradDiff2.append(rg[s] - rg[q])
            # print(gradDiff, gradDiff2)
            gradDiff = np.array(gradDiff)
            gradDiff2 = np.array(gradDiff2)
            f9 = np.sum(np.sqrt(np.sum(np.square(gradDiff), axis=1)))
            f10 = np.sum(np.sqrt(np.sum(np.square(gradDiff2), axis=1)))
            a = np.array([f1, f2, f4, f3, f10, f9, f8, f7, f5, f6])
            # a = np.array([ f2, f4, f3, f10, f9, f8, f7, f5, f6])
            if i >= 4 and j >= 4:
                w1 = 1 / (1 + abs(v[i][j]) + 2 * abs(v[i - 1][j]) + abs(v[i - 2][j]))
                w2 = 1 / (1 + abs(v[i][j]) + 2 * abs(v[i + 1][j]) + abs(v[i + 2][j]))
                w3 = 1 / (1 + abs(h[i][j]) + 2 * abs(h[i][j - 1]) + abs(h[i][j - 2]))
                w4 = 1 / (1 + abs(h[i][j]) + 2 * abs(h[i][j + 1]) + abs(h[i][j + 2]))
                warr = [w1 * v1, w2 * v3, w3 * v2, w4 * v4]
                predx = np.round(np.sum(warr) / np.sum([w1, w2, w3, w4]))
            else:
                predx = p
            test1[i][j] = p
            test2[i][j] = predx
            if np.mod(i + j, 2) == 0 and flag == 0:
                # print(a)
                prevalue = 0
                xmax = np.max([predx, p])
                xmin = np.min([predx, p])
                if xmax == xmin:
                    prevalue = xmax
                    typemap[i][j] = 1
                elif img_data[i][j] <= xmin - 1:
                    prevalue = xmin
                    typemap[i][j] = 2
                elif img_data[i][j] >= xmax:
                    prevalue = xmax
                    typemap[i][j] = 3
                else:
                    typemap[i][j] = 4
                # if i == 7 and j == 197:
                #     print('此时的', prevalue, typemap[i][j], xmax, xmin)
                # errolist[index] = int(img_data[i][j]) - int(prevalue)
                index += 1
                if prevalue != 0:
                    erromap[i][j] = int(img_data[i][j]) - int(prevalue)

            if np.mod(i + j, 2) == 1 and flag == 1:
                prevalue = 0
                xmax = np.max([predx, p])
                xmin = np.min([predx, p])
                if xmax == xmin:
                    prevalue = xmin
                    typemap[i][j] = 1
                elif img_data[i][j] <= xmin - 1:
                    prevalue = xmin
                    typemap[i][j] = 2
                elif img_data[i][j] >= xmax:
                    prevalue = xmax
                    typemap[i][j] = 3
                else:
                    typemap[i][j] = 4
                if prevalue != 0:
                    erromap[i][j] = int(img_data[i][j]) - int(prevalue)
    return erromap, typemap, test1, test2


def recover(em, cm, img_hide, RateList, flag3, PZlist, typemap, ecfinal):
    row, col = img_hide.shape
    secret = np.zeros(row * col)
    ec = np.ceil(ecfinal / 2)
    index = 0
    indextest = 0
    for i in range(2, row - 2):
        for j in range(2, col - 2):
            m = int(cm[i][j])
            types = 0
            if m != 999:
                if RateList[m] != 0:
                    P = PZlist[m][0]
                    Z = PZlist[m][1]
                    types = 1
                else:
                    types = 0
            # if i == 6 and j ==68:
            #     print('这个',P,typemap[i][j],ec,RateList[m],types,m,em[i][j])

            if np.mod(i + j, 2) == 0 and flag3 == 0 and types == 1 and typemap[i][j] != 4:
                if index == 65404:
                    print('这个时候的i,jrecover', i, j, em[i][j] + 255, P, Z, typemap[i][j], m)
                    indextest += 1
                if index == 65488:
                    print('这个时候的i,jrecover2', i, j, em[i][j] + 255, P, Z, typemap[i][j], m)
                    indextest += 1
                for k in range(len(P)):
                    if P[k] > Z[k] and RateList[m] > 0 and ec > 0:
                        # if em[index] == (P[k] - 255):
                        if em[i][j] == (P[k] - 255) and RateList[m] > 0:
                            secret[index] = 0
                            RateList[m] -= 1
                            ec -= 1
                            index += 1
                        if em[i][j] + 1 == (P[k] - 255) and RateList[m] > 0:
                            # if i == 6 and j == 68:
                            #     print('这个2', P[k], Z[k], typemap[i][j], ec, RateList[m], types, m, em[i][j])
                            #     print('此时index', index)
                            secret[index] = 1
                            RateList[m] -= 1
                            ec -= 1
                            index += 1
                    if P[k] < Z[k] and RateList[m] > 0 and ec > 0:
                        if em[i][j] == (P[k] - 255) and RateList[m] > 0:
                            # if em[index]  == (P[k] - 255):
                            secret[index] = 0
                            RateList[m] -= 1
                            ec -= 1

                            if index == 8:
                                print('此时i,j1', i, j, em[i][j], img_hide[i][j], P, typemap[i][j])
                            index += 1
                        if em[i][j] - 1 == (P[k] - 255) and RateList[m] > 0:
                            secret[index] = 1
                            RateList[m] -= 1
                            ec -= 1
                            if index == 8:
                                print('此时i,j2', i, j, em[i][j], img_hide[i][j])
                            index += 1
            if np.mod(i + j, 2) == 1 and flag3 == 1 and types == 1 and typemap[i][j] != 4:
                for k in range(len(P)):
                    if P[k] > Z[k] and RateList[m] > 0 and ec > 0:
                        # if em[index] == (P[k] - 255):
                        if em[i][j] == (P[k] - 255) and RateList[m] > 0:
                            secret[index] = 0
                            RateList[m] -= 1
                            ec -= 1
                            index += 1
                        if em[i][j] + 1 == (P[k] - 255) and RateList[m] > 0:
                            secret[index] = 1
                            secret.append(1)
                            RateList[m] -= 1
                            ec -= 1
                            index += 1
                    if P[k] < Z[k] and RateList[m] > 0 and ec > 0:
                        if em[i][j] == (P[k] - 255) and RateList[m] > 0:
                            # if em[index]  == (P[k] - 255):
                            secret[index] = 0
                            RateList[m] -= 1
                            ec -= 1
                            index += 1
                        if em[i][j] - 1 == (P[k] - 255) and RateList[m] > 0:
                            secret[index] = 1
                            RateList[m] -= 1
                            ec -= 1
                            index += 1
    print(ec, RateList)
    print('indextest', indextest)
    secret = secret[:index]
    return secret


def recovermethod(img, flag, PZlist, RateList, cm):
    v, h = get_grad(img)
    em, typemap = get_em(img, flag, v, h)
    secret = recover(em, cm, img, RateList, flag, PZlist, typemap)
    return secret


def get_complex_map(img, flag):
    '''
            计算图像的复杂度矩阵
            :param img: 图像
            :param flag: 奇数点还是偶数点
            :return:  复杂度矩阵
        '''
    row, col = img.shape
    # cv2.imshow('Lena', img)
    # cv2.waitKey(0)
    # print('row, col=', row, col)
    complex_map = np.zeros((row, col))
    complex_map2 = np.zeros(row * col)
    index = 0
    for i in range(2, row - 2):
        for j in range(2, col - 2):
            # 计算复杂度，直接跟阈值key比较
            # if complex[i][j]
            # 像素上下左右四个像素
            v1 = int(img[i - 1][j])  # p2
            v2 = int(img[i][j - 1])  # p1
            v3 = int(img[i + 1][j])  # p4
            v4 = int(img[i][j + 1])  # p3
            # 选中点
            x = int(img[i][j])  # xi
            # 其他九个点
            v5 = int(img[i - 2][j - 1])  # p8
            v6 = int(img[i - 1][j - 2])  # p7
            v7 = int(img[i + 1][j - 2])  # p6
            v8 = int(img[i + 2][j - 1])  # p5
            v9 = int(img[i + 2][j + 1])  # p12
            v10 = int(img[i + 1][j + 2])  # p11
            v11 = int(img[i - 1][j + 2])  # p10
            v12 = int(img[i - 2][j + 1])  # p9
            pixel12 = np.array([v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12])  # 像素周围的12个像素存到pixel12
            av = np.mean([v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12])  # 12像素的平均值，x0为论文中的m
            complex = np.sqrt(np.sum(np.square(pixel12 - av)) / 12)

            if np.mod(i + j, 2) == 0 and flag == 0:  # 偶数点
                complex_map[i][j] = complex
                complex_map2[index] = complex
                index += 1
            if np.mod(i + j, 2) == 1 and flag == 1:  # 奇数点
                complex_map[i][j] = complex
                complex_map2[index] = complex
                index += 1
    return complex_map, complex_map2
